package com.grupoconstruobras.sigo.configuracion.parametrizacion;

import com.grupoconstruobras.sigo.controller.IEditarActions;
import com.grupoconstruobras.sigo.controller.IGuardarActions;
import com.grupoconstruobras.sigo.controller.IVerActions;
import com.grupoconstruobras.sigo.core.config.IParamConfigAppBussines;
import com.grupoconstruobras.sigo.core.config.ParametroConfigAppDto;
import com.grupoconstruobras.sigo.ServiceException;
import com.grupoconstruobras.sigo.general.util.CRUDState;
import com.grupoconstruobras.siijt.exhumaciones.ui.mapper.SelectItemFactory;

import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;
import javax.faces.model.SelectItem;
import javax.faces.validator.ValidatorException;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;

import org.apache.commons.lang3.math.NumberUtils;

@Named("detalleParametroConfig")
@ViewScoped
public class DetalleParamConfigSistema implements IGuardarActions<Long, ParametroConfigAppDto>, IEditarActions<Long>,
    IVerActions<Long>, Serializable {

  private static final long serialVersionUID = 1L;

  private final Logger LOG = Logger.getLogger(this.getClass().getName());

  //@ManagedProperty("#{msgVal}")
  private ResourceBundle bundle;

  // Bussines
  @Inject
  protected IParamConfigAppBussines paramConfigBussines;

  @Inject
  protected SelectItemFactory selectItemFactory;
//  @Inject
//  protected IMaquinaEstados maquinaEstados;
  
  protected Map<String, Boolean> disabled;
  
  protected ParametroConfigAppDto paramConfgDto;

  protected SelectItem[] tipoDatoValues;

  private UIComponent components;
  
  // CRUD state
  protected CRUDState estado;

  public CRUDState getEstado() {
    return estado;
  }

  public DetalleParamConfigSistema() {
	FacesContext fc = FacesContext.getCurrentInstance();
	bundle = fc.getApplication().evaluateExpressionGet(fc, "#{msgVal}", ResourceBundle.class);
  }

  public void initView(ComponentSystemEvent event) {
	  components = event.getComponent();
  }
  
  @PostConstruct
  protected void init() {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    String action = (String) facesContext.getExternalContext().getRequestMap().get("action");

    inicializarCampos();

    if (action == null || action.equals("insertar")) {
      initCreateAction();
    }
    else {
      String parametroIdStr = (String) facesContext.getExternalContext().getRequestMap().get("parametroId");
      if (action.equals("view")) {
        initViewAction(Long.parseLong(parametroIdStr));
      }
      else if (action.equals("edit")) {
        initEditAction(Long.parseLong(parametroIdStr));
      }

      else {
        initCreateAction();
      }
    }
  }

  
  private void initEditAction(Long parametroId) {
	this.estado = CRUDState.EDITAR;
    toggleFields(disabled, false);
    editar(parametroId);
  }

  private void initCreateAction() {
	  this.estado = CRUDState.INSERTAR;
	  toggleFields(disabled, false);
	  paramConfgDto = paramConfigBussines.newInstance();
  }

  private void initViewAction(Long parametroId) {
	  this.estado = CRUDState.VER;
	  toggleFields(disabled, true);
	  ver(parametroId);
  }

  private void inicializarCampos() {
    // protected Map<String, Boolean> disabled;
    this.disabled = new HashMap<String, Boolean>();
    
    disabled.put("parametro", false);
    disabled.put("descripcion", false);
    disabled.put("tipodato", false);
    disabled.put("valor", false);

  }

  private void toggleFields(Map<String, Boolean> fields, boolean disabled) {
    Iterator<java.util.Map.Entry<String, Boolean>> it = fields.entrySet().iterator();
    while (it.hasNext()) {
      java.util.Map.Entry<String, Boolean> ent = it.next();
      ent.setValue(disabled);
    }
  }

  public SelectItem[] getTipoDatoValues() {
    SelectItem[] items = new SelectItem[ParamConfSistTDatoEnum.values().length];
    int i = 0;
    for(ParamConfSistTDatoEnum td: ParamConfSistTDatoEnum.values()) {
      items[i++] = new SelectItem(td, td.getLabel());
    }
    return items;
  }
  
  // Setters & Getters
  public Map<String, Boolean> getDisabled() {
    return disabled;
  }

  public ParametroConfigAppDto setParamConfgDto(ParametroConfigAppDto paramConfgDto) {
    return paramConfgDto;
  }

  public ParametroConfigAppDto getParamConfgDto() {
    return paramConfgDto;
  }

  public String guardarParametro() {
    FacesContext fc = FacesContext.getCurrentInstance();
    
    // validamos el valor ingresado
    try {
    	this.validarValorIngresado(fc);
    	
        // guardamos en tabla
    	this.guardar(paramConfgDto.getId(), paramConfgDto);

    	return "volverConfigParamConfig";

    } catch (ValidatorException e) {
	    LOG.severe(e.getMessage());
	}
	
    return null;
  }

  // Actions
  public void guardar(Long id, ParametroConfigAppDto dto) {
    if (CRUDState.INSERTAR.equals(this.estado) || CRUDState.EDITAR.equals(this.estado)) {
    	try {
	    	this.paramConfgDto = paramConfigBussines.save();
		} catch (ServiceException e) {
		    LOG.severe(e.getMessage());
		}
    }	
  }
    
  private void validarValorIngresado(FacesContext fc) throws ValidatorException {
	  boolean resp;
	  String msgBundle = "";
			  
	  UIInput component = (UIInput) components.findComponent("valor");
	  String valor = component.getValue().toString();
	  
	  switch (paramConfgDto.getTipoDato()) {
      case "NUMER":
    	  // Validamos que el valor ingresado sea de tipo numerico
    	  resp = NumberUtils.isNumber(valor);
    	  msgBundle = "configuracion.parametrizacion.validacion.dato_numerico";
          break;
      case "ALFAN":    	  
    	  resp = true;
          break;
      case "FECHA":
    	  // Validamos que el valor ingresado sea de tipo fecha
    	  SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
    	  try {
    		  df.parse(valor);
    		  resp = true;
    	  } catch (ParseException e) {
    		  resp = false;
	    	  msgBundle = "configuracion.parametrizacion.validacion.dato_fecha";
    	  }  
    	  break;
      default:
    	  resp = false;
	  }
	  if (resp == false) {
		String msg = bundle.getString(msgBundle);
		FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, null);
		fc.addMessage(component.getClientId(), message);
		fc.renderResponse();
		throw new ValidatorException(message);
	  }
}
  
@Override
  public void cancelar() {
    this.paramConfgDto = paramConfigBussines.newInstance();
  }

  public String cancelarEdit() {
	this.cancelar();
	return "volverConfigParamConfig";
  }

  @Override
  public void ver(Long id) {
    try {
      this.paramConfgDto = paramConfigBussines.get(id);
    } catch (ServiceException e) {
      LOG.severe(e.getMessage());
    }
  }

  @Override
  public void editar(Long id) {
    try {
      this.paramConfgDto = paramConfigBussines.get(id);
    } catch (ServiceException e) {
      LOG.severe(e.getMessage());
    }
  }
  
}
